﻿//        Another Demo from Andy L. & MissedMemo.com
// Borrow whatever code seems useful - just don't try to hold
// me responsible for any ill effects. My demos sometimes use
// licensed images which CANNOT legally be copied and reused.

using System;
using System.Linq;
using System.Windows;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Input;

using MissedMemo.MeatAndCheeseDisc.OrderEntry.OrderProcessing;


namespace MissedMemo.MeatAndCheeseDisc.OrderEntry
{
    public partial class MainWindow : Window
    {
        private OrderEntryServiceAbstraction _serviceAbstraction;


        public MainWindow()
        {
            InitializeComponent();

            // Set window caption equal to assembly info product name...

            object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( typeof( AssemblyProductAttribute ), false );
            if( attributes.Length > 0 )
                Title = ( (AssemblyProductAttribute)attributes[0] ).Product;
        }

        
        // Delay remote comms connection until AFTER window is first displayed

        protected override void OnContentRendered( EventArgs e )
        {
            base.OnContentRendered( e );

            if( false == DesignerProperties.GetIsInDesignMode( this ) )
            {
                _serviceAbstraction = new OrderEntryServiceAbstraction();
                _serviceAbstraction.NotifyPizzaIsDone += OnNotifyPizzaIsDone;
                
                Closing += (sender, args) => _serviceAbstraction.Close();
            }
        }

       
        private void OnAddOrder( object sender, RoutedEventArgs e )
        {
            OrderEditPanel.DataContext = new Order();
            OrderEditPanel.Open( layoutRoot.ActualHeight );
        }


        // Can't rely on 'SelectionChanged' event, because we often need
        // to click on a list item which is ALREADY selected, in order to edit it!

        private void listOrders_MouseLeftButtonUp( object sender, MouseButtonEventArgs e )
        {
            Order order = listOrders.SelectedItem as Order;

            if( order != null )
            {
                // (Binding to a clone enables CANCELLING changes)
                OrderEditPanel.DataContext = order.Clone();
                OrderEditPanel.Open( layoutRoot.ActualHeight );
            }
        }


        // Note: We could update App.OrderCollection directly in the edit view,
        // but it feels "correct" to group it here with Add/Edit/Delete opps.

        private void OnSaveChanges( object sender, ExecutedRoutedEventArgs e )
        {
            Order editedOrder = OrderEditPanel.DataContext as Order;

            if( editedOrder != null )
            {
                Order original = App.OrderCollection.FirstOrDefault( order => order.NowServingNumber == editedOrder.NowServingNumber );

                if( original == null ) // edits represent a NEW order
                {
                    editedOrder.DateTimeOrderPlaced = DateTime.Now;
                    App.OrderCollection.Add( editedOrder );
                    editedOrder.RequestStartCooking += OnStartCookingRequest;
                }
                else // replace EXISTING order with edited clone
                {
                    int i = App.OrderCollection.IndexOf( original );
                    App.OrderCollection[i] = editedOrder;

                    // As a simple hack, notify KitchenMonitor to DELETE original order,
                    // and send edited order as if it was a completely NEW order...

                    _serviceAbstraction.DeleteOrder( original.NowServingNumber );

                    if( editedOrder.ProcessingState == ProcessingState.Cooking )
                        _serviceAbstraction.ProcessOrder( editedOrder );
                }
            }
        }


        void OnStartCookingRequest( object sender, EventArgs e )
        {
            Order order = sender as Order;

            if( order != null )
            {
                _serviceAbstraction.ProcessOrder( order );
            }
        }


        private void OnDelete( object sender, ExecutedRoutedEventArgs e )
        {
            Order order = ((FrameworkElement)e.OriginalSource).DataContext as Order;

            if( order != null )
            {
                _serviceAbstraction.DeleteOrder( order.NowServingNumber );

                int i = App.OrderCollection.IndexOf( order );
                App.OrderCollection.Remove( order );

                // Remove refs, to enable garbage collection... (others?)
                order.RequestStartCooking -= OnStartCookingRequest;
            }
        }


        void OnNotifyPizzaIsDone( object sender, OrderEntryServiceAbstraction.PizzaFinishedEventArgs e )
        {
            Order order = App.OrderCollection.FirstOrDefault( o => o.NowServingNumber == e.NowServingNumber );

            if( order != null )
            {
                Pizza pizza = order.Items.FirstOrDefault( p =>
                                    p.IsDone == false
                                 && p.Type == e.FinishedPizza.Type
                                 && p.Size == e.FinishedPizza.Size
                              );

                if( pizza != null )
                {
                    pizza.IsDone = true;

                    // Mark order ready for pickup only when ALL pizzas are done

                    if( order.Items.All( p => p.IsDone ) )
                        order.ProcessingState = ProcessingState.Ready;
                }
            }
        }
    }
}
